﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SeleniumContext.cs" company="">
// </copyright>
// <summary>
//   The selenium context.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace UITest.Selenium.SeleniumContext
{
    using System;

    using OpenQA.Selenium;
    using OpenQA.Selenium.Remote;
    using OpenQA.Selenium.Support.UI;

    using UITest.Report;
    using UITest.Selenium.WebDrivers;

    /// <summary>
    ///     The selenium context.
    /// </summary>
    public class SeleniumContext : IDisposable
    {
        #region Fields

        /// <summary>
        ///     The report.
        /// </summary>
        public ReportListener Report;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SeleniumContext"/> class.
        /// </summary>
        /// <param name="remoteWebDriverProvider">
        /// The remote web driver provider.
        /// </param>
        public SeleniumContext(IRemoteWebDriverProvider remoteWebDriverProvider)
        {
            this.RemoteWebDriverProvider = remoteWebDriverProvider;
            this.WebDriver = this.RemoteWebDriverProvider.NewDriver();
            this.MainWindow = this.WebDriver.CurrentWindowHandle;
            ReportFactory.New();
            this.Report = ReportFactory.GetReportListener();
            this.TIMEOUT_SEC = 60;
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets or sets the main window.
        /// </summary>
        public string MainWindow { get; set; }

        /// <summary>
        ///     Gets or sets the remote web driver provider.
        /// </summary>
        public IRemoteWebDriverProvider RemoteWebDriverProvider { get; set; }

        /// <summary>
        ///     Gets or sets the timeout sec.
        /// </summary>
        public int TIMEOUT_SEC { get; set; }

        /// <summary>
        ///     Gets the web driver.
        /// </summary>
        public RemoteWebDriver WebDriver { get; private set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        ///     The dispose.
        /// </summary>
        public void Dispose()
        {
            if (this.WebDriver != null)
            {
                this.WebDriver.Quit();
                this.WebDriver = null;
            }
        }

        /// <summary>
        /// The wait until.
        /// </summary>
        /// <param name="isTrue">
        /// The is true.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="timeout">
        /// The timeout.
        /// </param>
        /// <param name="throwException">
        /// The throw exception.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool WaitUntil(
            Func<IWebDriver, bool> isTrue, 
            string message = "", 
            int timeout = -1, 
            bool throwException = false)
        {
            try
            {
                var wait = new WebDriverWait(this.WebDriver, TimeSpan.FromSeconds(this.TimeOut(timeout)));
                wait.Until(isTrue);
            }
            catch (Exception ex)
            {
                this.Report.WriteTestOutput(ex.ToString());

                if (throwException)
                {
                    throw;
                }

                return false;
            }

            return true;
        }

        #endregion

        #region Methods

        private int TimeOut(int timeout)
        {
            return timeout != -1 ? timeout : this.TIMEOUT_SEC;
        }

        #endregion
    }
}